﻿using LeRenard.Core.Numbers;
using System.Linq;

namespace LeRenard.ScriptWars.Model.Scripting
{
    /// <summary>
    /// Cycles through an <see cref="IAlgorithm"/> an keeps track of the current and previous <see cref="IOperation"/>s.
    /// </summary>
    public class AlgorithmCycler : IAlgorithmCycler
    {
        /// <summary>
        /// Holds the algorithm to cycle through.
        /// </summary>
        private IAlgorithm _algorithm;

        /// <summary>
        /// Gets the current line.
        /// </summary>
        public int CurrentLine { get { return _lineCycler.Current; } }
        private readonly IRangeCycler<int> _lineCycler;

        /// <summary>
        /// Gets the current operation.
        /// </summary>
        public IOperation CurrentOperation 
        { 
            get {
                var operation = _algorithm
                    .Operations
                    .Where(o => o.LineNumber.Equals(CurrentLine))
                    .Single();

                return operation;
            } 
        }

        #region Construction
        public AlgorithmCycler(IAlgorithm algorithm)
        {
            ThrowIf.Null(() => algorithm);

            var range = new Int32Range(1, algorithm.LineCount);
            var lineCycler = new Int32RangeCycler(range);

            _algorithm = algorithm;
            _lineCycler = lineCycler;
        }
        #endregion

        #region Methods
        /// <summary>
        /// Goes through the next line of the algorithm.
        /// </summary>
        public void Next()
        {
            _lineCycler.Next();
        }

        /// <summary>
        /// Resets the cycler to a specific line number.
        /// </summary>        
        public void Reset(int lineNumber)
        {
            ThrowIf.OutOfRange(() => lineNumber, _lineCycler.Range);

            _lineCycler.Reset(lineNumber);
        }
        #endregion
    }
}
